import 'dart:async';

import 'package:delightful_toast/delight_toast.dart';
import 'package:dio/dio.dart';
import 'package:e_book/http/dio_instance.dart';
import 'package:e_book/http/spider/spi_string.dart';
import 'package:e_book/model/activity.dart';
import 'package:e_book/model/author.dart';
import 'package:e_book/model/book.dart';
import 'package:e_book/model/review.dart';
import 'package:e_book/model/types.dart';
import 'package:html/dom.dart';
import 'package:html/parser.dart';

class SpiderApi {
  static SpiderApi? _instance;

  SpiderApi._();

  static SpiderApi instance() {
    return _instance ??= SpiderApi._();
  }

  // 获取图书详情数据
  /// [value] 图书信息
  Future<void> fetchBookDetail(
    Book value, {
    Function(Book value)? bookCallback,
    Function(List<Author> values)? authorCallback,
    Function(List<Review> values)? reviewCallback,
    Function(List<Book> values)? similarBooksCallback,
  }) async {
    String htmlStr = await DioInstance.instance()
        .getString(path: '${ApiString.bookDetailUrl}${value.id}');
    Document doc = parse(htmlStr);

    if (bookCallback != null) {
      bookCallback.call(_parseBookDetail(value, doc));
    }

    if (authorCallback != null) {
      authorCallback.call(_parseBookAuthor(doc));
    }

    if (reviewCallback != null) {
      reviewCallback.call(_parseBookReview(doc));
    }

    if (similarBooksCallback != null) {
      similarBooksCallback.call(_parseBookSimilarBooks(doc));
    }
  }

  // 解析豆瓣商城首页数据
  Future<void> fetchDoubanStoreData(
      {Function(List<Book> values)? weekBooksCallback,
      Function(List<Book> values)? top250Callback}) async {
    String htmlStr = await DioInstance.instance()
        .getString(path: ApiString.bookDoubanHomeUrl);
    Document doc = parse(htmlStr);

    // 解析一周新书
    if (weekBooksCallback != null) {
      weekBooksCallback.call(_parseWeekBooks(doc));
    }

    // 解析Top250排行榜
    if (top250Callback != null) {
      top250Callback.call(_parseTop250Books(doc));
    }
  }

  // 获取豆瓣商城新书速递
  Future<List<Book>> fetchExoressBooks() async {
    Response res = await DioInstance.instance()
        .get(path: ApiString.bookExpressJsonUrl, params: {
      'tag': BookExpressTag.all.value,
    });

    Document doc = parse(res.data['result']);

    // 解析 JSON 数据中拿到的html
    return _parseExpressBooks(doc);
  }

  //  获取首页数据
  Future fetchHomeData({
    Function(List<Activity>)? activitiesCallback,
    Function(List<String>)? activiLabelCallback,
    Function(List<Book>)? booksCallback,
  }) async {
    String htmlStr = await DioInstance.instance()
        .getString(path: ApiString.bookDoubanHomeUrl);
    Document doc = parse(htmlStr);
    // 解析活动数据 轮播图部分
    if (activitiesCallback != null) {
      activitiesCallback.call(parseBookActivities(doc));
    }
    // 解析所有活动标签数据
    if (activiLabelCallback != null) {
      activiLabelCallback.call(parseBookActiviLabels(doc));
    }
    // 解析 首页中的的html
    if (booksCallback != null) booksCallback.call(_parseExpressBooks(doc));
  }

  // 解析活动数据
  List<Activity> parseBookActivities(Document doc) {
    List<Element> aEls =
        doc.querySelectorAll('.books-activities .book-activity');
    List<Activity> activities = [];
    for (Element a in aEls) {
      String url = a.attributes['href']?.trim() ?? "";
      String cover = ApiString.getBookActivityCover(a.attributes['style']);
      String title = a.querySelector('.book-activity-title')?.text.trim() ?? "";
      String label = a.querySelector('.book-activity-label')?.text.trim() ?? "";
      String time = a.querySelector('.book-activity-time')?.text.trim() ?? "";
      activities.add(Activity(
        url: url,
        cover: cover,
        title: title,
        label: label,
        time: time,
      ));
    }
    return activities;
  }

  // 解析所有活动标签数据
  List<String> parseBookActiviLabels(Document doc) {
    List<Element> spanEls =
        doc.querySelectorAll('.books-activities .hd .tags .item');
    List<String> labels = [];
    for (Element span in spanEls) {
      labels.add(span.text.trim());
    }
    return labels;
  }

  // 解析书籍数据
  List<Book> _parseExpressBooks(Document doc) {
    List<Book> books = [];
    // 只获取一页
    Element ulEls = doc.querySelectorAll('.books-express .bd .slide-item')[1];
    List<Element> liEls = ulEls.querySelectorAll('li');
    for (Element li in liEls) {
      Element? a = li.querySelector('.cover a');
      // 解析id
      String id = ApiString.getBookId(
          a?.attributes['href']?.trim() ?? "", ApiString.bookIdRegExp);
      String cover = a?.querySelector('img')?.attributes['src'] ?? '';
      String title = li.querySelector('.info .title a')?.text.trim() ?? "";
      String authorName = li.querySelector('.info .author')?.text.trim() ?? "";
      books.add(Book(
        id: id,
        cover: cover,
        title: title,
        authorName: authorName,
        // cover
        // title
        // authorName
        // rate
        // price
      ));
    }
    return books;
  }

  // 解析一周新书
  List<Book> _parseWeekBooks(Document doc) {
    List<Element> liEls = doc.querySelectorAll('.popular-books .bd ul li');
    return liEls.map((li) {
      //封面
      String? cover = li.querySelector('.cover img')?.attributes['src'];

      // 标题
      Element? aEl = li.querySelector('.title a');
      String? title = aEl?.text.trim();

      // ID
      String? id =
          ApiString.getBookId(aEl?.attributes['href'], ApiString.bookIdRegExp);

      // 作者
      String? authorName = li.querySelector('.author')?.text.trim() ?? '';
      authorName = authorName.replaceFirst('作者：', ''); // 删除作者

      // 副标题
      String? subTitle;
      if (title != null && title.isNotEmpty) {
        List titles = title.split(': ');
        if (titles.length > 1) {
          title = titles[0];
          subTitle = titles[1];
        } else {
          subTitle = authorName;
        }
      }

      // 评分
      double rate = parseRate(li.querySelector('.average-rating')?.text.trim());

      return Book(
        id: id,
        title: title,
        cover: cover,
        authorName: authorName,
        subTitle: subTitle,
        rate: rate,
      );
    }).toList();
  }

  double parseRate(String? rateStr) {
    if (rateStr == null || rateStr.isEmpty) return 0.0;
    try {
      return double.parse(rateStr);
    } catch (e) {
      return 0.0;
    }
  }

  // 解析Top250排行榜
  List<Book> _parseTop250Books(Document doc) {
    List<Element> dlEls = doc.querySelectorAll('#book_rec dl');
    return dlEls.map((dl) {
      //封面
      String? cover = dl.querySelector('dt img')?.attributes['src'];

      // 标题
      Element? aEl = dl.querySelector('dd a');
      String? title = aEl?.text.trim();

      // ID
      String? id =
          ApiString.getBookId(aEl?.attributes['href'], ApiString.bookIdRegExp);

      return Book(
        id: id,
        title: title,
        cover: cover,
      );
    }).toList();
  }

  // 解析图书详情
  Book _parseBookDetail(Book value, Document doc) {
    Element? bookEl = doc.querySelector('.subjectwrap');
    if (bookEl == null) return value;
    // 图书定价 页码 评分
    String? text = bookEl.querySelector('#info')?.text.trim();
    // 页码
    value.page = ApiString.getBookPage(text);
    // 定价
    value.price = ApiString.getBookPrice(text);
    // 评分
    value.rate =
        parseRate(bookEl.querySelector('.rating_num')?.text.trim() ?? '');

    // 内容简介
    String desc =
        doc.querySelector('.related_info .all .intro')?.text.trim() ?? '';
    if (desc.isEmpty) {
      // 没有展开按钮
      desc = doc.querySelector('.related_info .intro')?.text.trim() ?? '';
    }
    value.description = desc;

    // 购买信息
    List<Element> buyInfoEls = doc.querySelectorAll('.buyinfo ul li');
    value.buyInfo = buyInfoEls.map((buyInfoEl) {
      String? name =
          buyInfoEl.querySelector('.vendor-name a')?.text.trim() ?? '';
      String? price =
          buyInfoEl.querySelector('.price-wrapper a')?.text.trim() ?? '';
      price = price.replaceFirst('元', '');
      String? url =
          buyInfoEl.querySelector('.vendor-name a')?.attributes['href'];
      return BuyInfo(
        name: name,
        price: parseRate(price),
        url: url,
      );
    }).toList();
    return value;
  }

  // 解析图书作者数据
  List<Author> _parseBookAuthor(Document doc) {
    List<Element> liEls = doc.querySelectorAll('.authors-list .author');
    List<Author> authors = [];

    for (int i = 0; i < liEls.length - 1; i++) {
      Element li = liEls[i];

      // 作者id
      String? authorId = ApiString.getBookId(
          li.children[0].attributes['href'], ApiString.authorIdRegExp);

      Element infoEl = li.children[1];

      authors.add(
        Author(
          id: authorId,
          avatar: li.children[0].children[0].attributes['src'],
          name: infoEl.children[0].text, //作者姓名
          role: infoEl.children[1].text, //角色
        ),
      );
    }
    return authors;
  }

  // 解析图书评论数据
  List<Review> _parseBookReview(Document doc) {
    List<Element> itemEls = doc.querySelectorAll('.review-list .review-item');
    List<Review> reviews = [];
    for (int i = 0; i < itemEls.length; i++) {
      if (i == 5) break;

      Element item = itemEls[i];
      Element hdEl = item.children[0];
      Element bdEl = item.children[1];

      // 作者
      Author author = Author(
        avatar: hdEl.querySelector('.avator img')?.attributes['src'],
        name: hdEl.querySelector('.name')?.text,
      );

      // 评分
      // Review.getRate(
      //     bdEl.querySelector('.main-title-rating')?.attributes['class']);
      double? rate = ApiString.getBookRate(
        hdEl.querySelector('.main-title-rating')?.attributes['class'] ?? '',
      );
      // 时间
      String? date = hdEl.querySelector('.main-meta')?.text.trim();

      // 短评
      String? short = bdEl.querySelector('.short-content')?.text ?? '';
      short = short
          .replaceFirst('(展开)', '')
          .replaceFirst('这篇书评可能有关键情节透露', '')
          .trim();

      reviews.add(Review(
        author: author,
        rate: rate,
        date: date,
        short: short,
      ));
    }
    return reviews;
  }

  // 解析图书推荐数据
  List<Book> _parseBookSimilarBooks(Document doc) {
    List<Element> dlEls = doc.querySelectorAll('#db-rec-section .content dl');
    List<Book> books = [];
    for (var dl in dlEls) {
      // 排除 .clean 无效数据
      if (dl.className == 'clear') continue;

      // 封面
      String? cover = dl.querySelector('dt img')?.attributes['src'];

      // 标题
      Element? aEl = dl.querySelector('dd a');
      String? title = aEl?.text.trim();

      // ID
      String? id =
          ApiString.getBookId(aEl?.attributes['href'], ApiString.bookIdRegExp);

      // 评分
      double? rate = parseRate(
        dl.querySelector('.subject-rate')?.text ?? '',
      );

      books.add(
        Book(
          id: id,
          title: title,
          cover: cover,
          rate: rate,
        ),
      );
    }
    return books;
  }
}
